package server;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.*;
import java.util.ArrayList;

import common.Carnivoro;
import common.Casella;
import common.ClientSocket;
import common.Dinosauro;
import common.Player;
import eccezioni.MyException;

public class GestisciClients extends Thread implements Serializable{

	private Socket socket;
	
	private BufferedReader bufferedReader;
	private BufferedWriter bufferedWriter;
	private ClientSocket ci;
	private Server server;
	private int ptk;
	boolean opensocket;
	private ArrayList<Player> pl;
	private ArrayList<Dinosauro> din;
	
	public GestisciClients(Socket s, Server ser){
		socket=s;
		server=ser;
		ci=new ClientSocket(socket);
		server.getClientinterface().add(ci);
		opensocket=true;
	}
	

	public void run(){
		int j, k, l, m, n, o, p, q, r, s, token, a, b;
		String result,u,v,x,z;
		try{
			bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		while(opensocket){
			String line = bufferedReader.readLine();
			if(line==null)
				break;
			char[] mex = line.toCharArray();
			for(j=0;mex[j]!='@';j++);
			for(k=j+1;mex[k]!=',';k++);
			String command=line.substring(j+1,k);
						
			if(command.equals("creaUtente")){
				
				for(l=k+2;mex[l]!='=';l++);
				for(m=l+2;mex[m]!=',';m++);
				u=line.substring(l+1, m);
				
				for(n=m+2;mex[n]!='=';n++);
				for(o=n+2;o<mex.length;o++);
				v=line.substring(n+1, o);
				
				result=new String(server.creaPlayer(u,v));
				
				ci.display(result);
			}
			
			if(command.equals("login")){
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;mex[m]!=',';m++);
				u=line.substring(l+1, m);
				
				for(n=m+1;mex[n]!='=';n++);
				for(o=n+1;o<mex.length;o++);
				v=line.substring(n+1, o);
				
				result=new String(server.login(u,v));
								
				if(result.charAt(1)=='a')
					ci.display(result);
				else{
					token=server.getToken().get((server.getToken().size())-1);
					ptk=token;
					ci.setToken(token);
					ci.display(result);
				}
			
			}
			
			
			if(command.equals("creaRazza")){
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;mex[m]!=',';m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
				
				for(n=m+1;mex[n]!='=';n++);
				for(o=n+1;mex[o]!=',';o++);
				v=line.substring(n+1, o);
				
				for(p=o+1;mex[p]!='=';p++);
				char nut=line.charAt(p+1);
				
				result=new String(server.creaRazza(v,token,nut));
				
				ci.display(result);
			}
				
			if(command.equals("accessoPartita")){
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				

				result=new String(server.entraInPartita(token));
				
				ci.display(result);
				
			}
				
			if(command.equals("uscitaPartita")){
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				result=new String(server.esciDallaPartita(token));
				
				ci.display(result);
						
			}
				
			
			if(command.equals("listaGiocatori")){
				
				String listGiocatori;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				try {
					pl=server.listaGiocatori(token);
					listGiocatori=new String("@listaGiocatori");
					if(pl.size()!=0){ 
						for(Player px:pl)
							listGiocatori+="," + px.getNomeutente();
						listGiocatori+=",";
					}
					else
						listGiocatori+=" ";
					ci.display(listGiocatori);
				} catch (MyException e) {
					ci.display(e.getMessage());
				}
		
			}
				
				
			if(command.equals("classifica")){
				
				String classifica;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				try {
					pl=server.classifica(token);
					
					classifica=new String("@classifica");
					if(classifica.length()==0)
						classifica+=" ";
					else{
						for(Player px:pl)
							classifica+= (",{" + px.getNomeutente()+ ","+ px.getNomespecie() +"," + px.getPunteggio() + ","+px.getEstchar()+"}");
					}
					ci.display(classifica);
				} catch (MyException e) {
					ci.display(e.getMessage());
				}
				
			}
				
			
			if(command.equals("logout")){
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				result=new String(server.logout(token));
				
				ci.display(result);
			
			}
			
			
			if(command.equals("mappaGenerale")){
				
				char[][] mp = new char[40][40];
				String mappagen;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				try {
					mp = server.mappaGenerale(token);
					mappagen = new String("@mappaGenerale,");
					mappagen+="{40,40},";
					for(int io=0;io<40;io++)
						for(int jo=0;jo<40;jo++){
							mappagen+="[" + mp[io][jo] + "]";
							if(jo==39)
								mappagen+=";";
						}
					ci.display(mappagen);
				}  catch (MyException e) {
					ci.display(e.getMessage());
				}
				
			}
			
			if(command.equals("listaDinosauri")){
				
				String str;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				try {
					din=server.listaDinosauri(token);
					str = new String("@listaDinosauri");
					try{
						server.checkGiocatoreOnline(server.getPDaToken(token).getNomeutente());
						for(Dinosauro dinosa:din)
							str+=",(" + dinosa.getId() + ")";
						ci.display(str);
					}catch (MyException f){
						ci.display(str+"+");
					}
					
				} catch (MyException e) {
					ci.display(e.getMessage());
				}
				
			}
			
			if(command.equals("listaDinosauriGlobal")){
				
				String str;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;m<mex.length;m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
						
				try {
					din=server.listaDinosauriGlobal(token);
					str = new String("@listaDinosauriGlobal");
					try{
						server.checkGiocatoreOnline(server.getPDaToken(token).getNomeutente());
						for(Dinosauro dinosa:din)
							str+=",(" + dinosa.getId() +","+dinosa.getNomepadrone()+")";
						ci.display(str);
					}catch (MyException f){
						ci.display(str+"+");
					}
					
				} catch (MyException e) {
					ci.display(e.getMessage());
				}
				
			}
			
			
			if(command.equals("vistaLocale")){
				
				String stringa="@vistaLocale,";
				Casella[][] vist;
				int xo=0,yo=0,dimo=0,dimi=0,posi,posj;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;mex[m]!=',';m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
				
				for(n=m+1;mex[n]!='=';n++);
				for(o=n+1;o<mex.length;o++);
				v=line.substring(n+1, o);
				p=Integer.parseInt(v);	
				
				posi=server.getPDaToken(token).getDino(p).getCurrentpositioni();
				posj=server.getPDaToken(token).getDino(p).getCurrentpositionj();
				
				try {
					vist=server.vistaLocale(token,p);
					switch(vist.length){
						case 5:
							xo=posi+2;
							yo=(posj-2);
							dimo=5;
							dimi=5;					
							break;
						case 7:
							xo=posi+3;
							yo=(posj-3);
							dimo=7;
							dimi=7;
							break;
						case 9:
							xo=posi+4;
							yo=(posj-4);
							dimo=9;
							dimi=9;
							break;
					}
					
					stringa+="{"+xo+","+yo+"},{"+dimo+","+dimi+"},"; 
					
					String[][] vis = server.getGame().visualeLocale(server.getPDaToken(token).getDino(p));
					
					for(int i=0;i<vis.length;i++)
						for(int jj=0;jj<vis.length;jj++){
							stringa+="[" + vis[i][jj] + "]";
							if(jj==(vis.length-1))
								stringa+=";";
						}
					
					System.out.println(stringa);
	
					ci.display(stringa);

				} catch (MyException e) {
					ci.display(e.getMessage());
				}

			}
				
				
			if(command.equals("statoDinosauro")){
				
				Dinosauro sc;
				String state=new String("@statoDinosauro,");	
				char nutri;
				
				for(l=k+1;mex[l]!='=';l++);
				for(m=l+1;mex[m]!=',';m++);
				u=line.substring(l+1, m);
				token=Integer.parseInt(u);				
				
				for(n=m+1;mex[n]!='=';n++);
				for(o=n+1;o<mex.length;o++);
				v=line.substring(n+1, o);
				p=Integer.parseInt(v);	
				
				try{
					sc=server.statoDinosauro(token,p);
					if(sc instanceof Carnivoro)
						nutri='c';
					else
						nutri='e';
					if(sc.getEta()!=-1)
						state+= sc.getNomepadrone() + ","+ sc.getNomespecie() + ","+ nutri + ",{"+ (39-sc.getCurrentpositioni()) + ","+ sc.getCurrentpositionj() +"},"+ sc.getD() +","+ sc.getEnergia() +","+ sc.getEta();
					else
						state+= sc.getNomepadrone() + ","+ sc.getNomespecie() + ","+ nutri + ",{"+ (39-sc.getCurrentpositioni()) + ","+ sc.getCurrentpositionj() +"},"+ sc.getD()+",N/A,N/A";
					ci.display(state);
				} catch (MyException e) {
					ci.display(e.getMessage());
				}
	
			}
				
			if(command.equals("muoviDinosauro")){
				
					for(l=k+1;mex[l]!='=';l++);
					for(m=l+1;mex[m]!=',';m++);
					u=line.substring(l+1, m);
					token=Integer.parseInt(u);				
					
					for(n=m+1;mex[n]!='=';n++);
					for(o=n+1;mex[o]!=',';o++);
					v=line.substring(n+1, o);
					s=Integer.parseInt(v);	
					
					for(p=o+1;mex[p]!='{';p++);
					for(q=p+1;mex[q]!=',';q++);
					z=line.substring(p+1, q);
					a=Integer.parseInt(z);
					
					for(r=q+1;mex[r]!='}';r++);
					x=line.substring(q+1,r);
					b=Integer.parseInt(x);
									
					result=new String(server.muoviDinosauro(token,s,a,b));
					
					ci.display(result);	
				
			}
				
				
				
				
		
			if(command.equals("cresciDinosauro")){

					for(l=k+1;mex[l]!='=';l++);
					for(m=l+1;mex[m]!=',';m++);
					u=line.substring(l+1, m);
					token=Integer.parseInt(u);				
					
					for(n=m+1;mex[n]!='=';n++);
					for(o=n+1;o<mex.length;o++);
					v=line.substring(n+1, o);
					p=Integer.parseInt(v);	
					
					result=new String(server.cresciDinosauro(token,p));
					
					ci.display(result);	
									
			}
				
				
			if(command.equals("deponiUovo")){

					for(l=k+1;mex[l]!='=';l++);
					for(m=l+1;mex[m]!=',';m++);
					u=line.substring(l+1, m);
					token=Integer.parseInt(u);				
					
					for(n=m+1;mex[n]!='=';n++);
					for(o=n+1;o<mex.length;o++);
					v=line.substring(n+1, o);
					p=Integer.parseInt(v);	
					
					result=new String(server.deponiUovo(token,p));
					
					ci.display(result);	
					
			}
				
			
				
				
				
			if(command.equals("confermaTurno")){
				
					for(l=k+1;mex[l]!='=';l++);
					for(m=l+1;m<mex.length;m++);
					u=line.substring(l+1, m);
					token=Integer.parseInt(u);				
					
					result=new String(server.confermaTurno(token));
					
					ci.display(result);
					
			}
				
			
			if(command.equals("passaTurno")){
				
					for(l=k+1;mex[l]!='=';l++);
					for(m=l+1;m<mex.length;m++);
					u=line.substring(l+1, m);
					token=Integer.parseInt(u);				
					
					result=new String(server.passaTurno(token));
					
					ci.display(result);
					
			}
			
			
			if(command.equals("chiudiSocket")){
				
				try{
					server.getPDaToken(ptk).getNomeutente();
					System.out.println("L'utente " + server.getPDaToken(ptk).getNomeutente() + " ha abbandonato il gioco.");
					//server.closeg(server.getPDaToken(ptk).getNomeutente());
					opensocket=false;
				}catch(NullPointerException e){
					System.out.println("L'utente con token "+ ptk+ " ha abbandonato il gioco.");
					opensocket=false;
				}
			}
				
			
		}	
	  bufferedReader.close();
   	  bufferedWriter.close();
   	  socket.close();
	  }catch(IOException e){
		  	try {
		  		bufferedReader.close();
				bufferedWriter.close();
				socket.close();
			} catch (IOException e1) {
				System.out.println("Socket chiuso");
			}
		  	this.interrupt();
	  }
	}


	public void setBufferedReader(BufferedReader bufferedReader) {
		this.bufferedReader = bufferedReader;
	}


	public BufferedReader getBufferedReader() {
		return bufferedReader;
	}
	
	
	public BufferedWriter getBufferedWriter() {
		return bufferedWriter;
	}


	public void setBufferedWriter(BufferedWriter bufferedWriter) {
		this.bufferedWriter = bufferedWriter;
	}
	
	
}
